import json, random, re

from django.contrib.auth import login, authenticate, logout
from django.http import JsonResponse, HttpResponse
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection
# Create your views here.
from libs.captcha.captcha import captcha
from libs.qiniuyun.qiniu_storage import storage, QINIUYUN_URL
from libs.yuntongxun.sms import CCP
import logging

from users.models import User
from users.utils import LoginRequiredMixin

logger = logging.getLogger('django')


# 图形验证码
class imagecodeView(View):
    def get(self, request):
        cur = request.GET.get('cur')
        pre = request.GET.get('pre', None)
        # 1.调用工具类 captcha 生成图形验证码
        text, image = captcha.generate_captcha()
        print('图形验证码:', text)

        # 2.链接 redis, 获取链接对象
        redis_conn = get_redis_connection('verify_code')

        # 3.利用链接对象, 保存数据到 redis, 使用 setex 函数
        # redis_conn.setex('<key>', '<expire>', '<value>')
        redis_conn.setex('img_%s' % cur, 300, text)

        # 4.返回(图片)
        return HttpResponse(image,
                            content_type='image/jpg')


# 短信验证码
class smscodeView(View):
    """短信验证码"""

    def post(self, request):

        date = json.loads(request.body.decode())
        mobile = date.get('mobile')
        text = date.get('text')  # 图形验证码内容
        id = date.get('id')  # 图形验证码id
        if not all([mobile, id, text]):
            return JsonResponse({'errno': '4002',
                                 'errmsg': '无数据'})

        # 链接redis, 获取链接对象
        redis_conn = get_redis_connection('verify_code')
        # 进入函数后, 先获取存储在 redis 中的时间参考数据
        send_flag = redis_conn.get('send_flag_%s' % mobile)
        # 查看数据是否存在, 如果存在, 说明60s没过, 返回
        if send_flag:
            return JsonResponse({'code': 400,
                                 'errmsg': '发送短信过于频繁'})

        # 提取验证码
        image_code = redis_conn.get('img_%s' % id)
        if image_code is None:
            # 图形验证码过期或者不存在
            return JsonResponse({'errno': '4002',
                                 'errmsg': '图形验证码失效'})
        # 删除图形验证码，避免恶意测试图形验证码
        try:
            redis_conn.delete('img_%s' % id)
        except Exception as e:
            logger.error(e)

        # 对比图形验证码
        image_code = image_code.decode()
        if text.lower() != image_code.lower():
            return JsonResponse({'errno': '4004',
                                 'errmsg': '图形验证码有误'})

        sms = '%06d' % random.randint(0, 999999)
        print('短信验证码(测试):', sms)

        # 创建管道对象:
        pl = redis_conn.pipeline()
        # 短信验证码有效期，单位：300秒
        # redis_conn.setex('sms_%s' % mobile, 300, sms)
        pl.setex('sms_%s' % mobile, 300, sms)
        # 往redis中存入时间参考数据, key值和value值随意指定, 但是时间必须为60s
        # redis_conn.setex('send_flag_%s' % mobile, 60, 1)
        pl.setex('send_flag_%s' % mobile, 60, 1)
        # 执行管道:
        pl.execute()

        ccp = CCP()
        # 注意： 测试的短信模板编号为1
        a = ccp.send_template_sms(mobile, [sms, 5], 1)
        print('a = ', a)
        return JsonResponse({
            'errno': "0",
            'errmsg': '发送成功'
        })


# 注册
class RegisterView(View):
    def post(self, request):
        data = json.loads(request.body.decode())
        mobile = data.get('mobile')
        phonecode = data.get('phonecode')
        password = data.get('password')
        # 整体检验
        if not all([mobile, phonecode, password]):
            return JsonResponse({
                'errno': '4002',
                'errmsg': '无数据'
            })
        # 手机号
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return JsonResponse({
                'errno': '4103',
                'errmsg': '手机号错误'
            })
        try:
            user = User.objects.get(mobile=mobile)
            if user:
                return JsonResponse({
                    'errno': '4004',
                    'errmsg': '手机号已存在'
                })
        except Exception as e:
            pass

        # 链接数据库
        redis_conn = get_redis_connection('verify_code')
        sms_code_server = redis_conn.get('sms_%s' % mobile)
        if not sms_code_server:
            return JsonResponse({'errno': '4004',
                                 'errmsg': '短信验证码过期'})
        # 对比验证码
        if phonecode != sms_code_server.decode():
            return JsonResponse({'errno': '4004',
                                 'errmsg': '验证码有误'})
        # 验证成功保存数据库
        try:
            user = User.objects.create_user(username=mobile,
                                            password=password,
                                            mobile=mobile)
        except Exception as e:
            return JsonResponse({
                'errno': '4004',
                'errmsg': '验证码有误'
            })
        # 添加如下代码
        # 实现状态保持
        login(request, user)

        return JsonResponse({
            'errno': '0',
            'errmsg': 'ok'
        })


# 登录
class LoginView(View):
    '''登录'''
    """判断是否登录"""
    def get(self, request):
        """判断是否登录"""
        if request.user.is_authenticated:
            return JsonResponse({"errno": "0",
                                 "errmsg": "已登录",
                                 "data": {"name": request.user.username,
                                          'user_id': request.user.id}})
        else:
            return JsonResponse({"errno": "4101",
                                 "errmsg": "未登录"})

    """登录接口"""
    def post(self, request):
        """登录接口"""
        data = json.loads(request.body.decode())
        mobile = data.get('mobile')
        password = data.get('password')

        # 校验(整体 + 单个)
        if not all([mobile, password]):
            return JsonResponse({
                'errno': '4002',
                'errmsg': '缺少必传参数'
            })
        # 验证是否能够登录
        user = authenticate(username=mobile,
                            password=password)
        # 判断是否为空, 如果为空, 返回
        if user is None:
            return JsonResponse({
                'errno': '4002',
                'errmsg': '用户名或者密码错误'
            })

        # request.session.set_expiry(None)
        response = JsonResponse({
            'errno': '0',
            'errmsg': '登录成功'
        })
        # 状态保持
        login(request, user)
        response.set_cookie('username',
                            user.username,
                            max_age=3600 * 24 * 14)
        return response

    """退出登录"""
    def delete(self, request):
        """退出登录"""
        logout(request)
        response = JsonResponse({"errno": "0",
                                 "errmsg": "已登出"})
        response.delete_cookie('username')
        return response


# 用户中心
class UserView(LoginRequiredMixin, View):
    def get(self, request):
        user = request.user
        data = {
            'avatar_url': QINIUYUN_URL + str(user.avatar),
            # 创建时间
            'create_time': user.date_joined.strftime('%Y-%m-%d %H:%M:%S'),
            'mobile': user.mobile,
            'name': user.username,
            'user_id': user.id
        }
        return JsonResponse({
            'data': data,
            'errmsg': 'ok',
            'errno': '0'
        })


# 上传头像
class UserAvatar(LoginRequiredMixin, View):
    def post(self, request):
        img = request.FILES.get('avatar', None)
        if img:
            avatar = storage(img.read())
            img_url = QINIUYUN_URL + avatar
            # print(img_url)
            request.user.avatar = avatar
            request.user.save()
            data = {'avatar_url': img_url}
            return JsonResponse({
                'data': data,
                'errmsg': '头像上传成功',
                'errno': '0'
            })
        else:
            return JsonResponse({
                "errno": "4002	",
                "errmsg": "无数据"
            })


# 用户名修改
class UserName(LoginRequiredMixin, View):
    def put(self, request):
        user = request.user
        new_name = json.loads(request.body.decode()).get('name')
        if not new_name:
            return JsonResponse({
                'errmsg': '缺少参数',
                'errno': '4103'
            })
        try:
            users = User.objects.get(username=new_name)
            if users:
                return JsonResponse({
                    'errmsg': '用户名已存在',
                    'errno': '4003'
                })
        except:
            pass
        user.username = new_name
        user.save()
        return JsonResponse({
            'errmsg': '修改成功',
            'errno': '0'
        })


# 实名认证
class RealName(LoginRequiredMixin, View):
    def post(self, request):
        data = json.loads(request.body.decode())
        real_name = data.get('real_name')
        id_card = data.get('id_card')
        if not all([real_name, id_card]):
            return JsonResponse({
                'errmsg': '缺少参数',
                'errno': '4103'
            })
        # 身份证简易格式判断
        try:
            id_cards = User.objects.get(id_card=id_card)
            if id_cards:
                return JsonResponse({
                    'errmsg': '身份证号已存在',
                    'errno': '4003'
                })
        except:
            pass
        """为方便测试暂不填写"""
        # 其他判断身份证方式(为方便测试暂不填写)
        # if not re.match(
        #     r"([1 - 9]\d{5}(18 | 19 | ([23]\d))\d{2}((0[1 - 9]) | (10 | 11 | 12))(([0 - 2][1 - 9]) | 10 | 20 | 30 | 31)\d{3}[0 - 9Xx]$) | ([1 - 9]\d{5}\d{2}((0[1-9]) | (10 | 11 | 12))(([0 - 2][1 - 9]) | 10 | 20 | 30 | 31)\d{2}$)"
        #     ,id_card
        # ):
        #     return JsonResponse({
        #         'errmsg': '身份证号错误',
        #         'errno': '4103'
        #     })
        request.user.real_name = real_name
        request.user.id_card = id_card
        request.user.save()

        return JsonResponse({
            'errmsg': '认证信息保存成功',
            'errno': '0'
        })

    def get(self, request):
        user = request.user
        data = {
            'real_name': user.real_name,
            'id_card': user.id_card
        }

        return JsonResponse({
            'data': data,
            'errmsg': 'ok',
            'errno': '0'
        })


